package demo.utils;

import demo.config.DateConfig;
import demo.config.DateTimeFormterGet;

import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class RedisUtils {

    /**
     * 根据对象 来得到属性与属性值的map集合
     * @param object 数据对象
     * @param <T> 对象的类型
     * @return map集合
     */
    public static<T> Map<String,Object> getHashByObject(T object){
        if(object == null){
            return null;
        }
        Map<String,Object> map = new HashMap<>();
        List<String> propertiesName = getPropertiesName(object);

        propertiesName.forEach(x->{
            try {
                map.put(x,getProperValue(object,x));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        return map;
    }

    /**
     * 根据class 和map集合来得到 完整的对象
     * @param clazz
     * @param map 属性值 集合
     * @param <T> 泛型
     * @return 完整的对象
     * @throws Exception
     */
    public static<T> T getObjectByHash(Class<T> clazz,Map<String,Object> map) throws Exception {
        List<String> propertiesName = getPropertiesName(clazz);
        Object ret = clazz.getDeclaredConstructor().newInstance();
        propertiesName.forEach(x->{
            try {
                setProperValue(ret,x,map.get(x));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        return (T) ret;
    }


    public static<T> T getObjectByObjectHash(Class<T> clazz,Map<Object,Object> map) throws Exception {
        Map<String, Object> stringObjectMap = mapConvert(map);
        T ret = getObjectByHash(clazz, stringObjectMap);
        return (T)ret;
    }

    public static Map<String,Object> mapConvert(Map<Object,Object> map){
        Map<String,Object> stringMap = new HashMap<>();
        map.forEach((x,y)->{
            stringMap.put(String.valueOf(x),y);
        });
        return stringMap;
    }

    /**
     *
     * @param obj 对象
     * @return 返回该对象的属性集合
     */
    public static List<String> getPropertiesName(Object obj){
        List<String> list = getPropertiesName(obj.getClass());
        return list;
    }

    public static List<String> getPropertiesName(Class clazz){
        Field[] declaredFields = clazz.getDeclaredFields();
        List<String> list = new ArrayList<>();
        for (Field declaredField : declaredFields) {
            list.add(declaredField.getName());
        }
        return list;
    }

    /**
     *
     * @param obj 属性对象
     * @param fieldName 对象的属性
     * @return 返回对象该属性的值
     * @throws Exception
     */
    public static Object getProperValue(Object obj,String fieldName) throws Exception {
        Object invoke = obj.getClass().getDeclaredMethod("get" + firstUpper(fieldName), null).invoke(obj, null);
        return invoke;
    }

    public static void setProperValue(Object obj,String fieldName,Object value) throws Exception {
        Class clazz = obj.getClass();
        Field field = clazz.getDeclaredField(fieldName);
        if(field.getType().getName().contains("LocalDateTime")){
            clazz.getDeclaredMethod("set"+firstUpper(fieldName),field.getType()).invoke(obj,LocalDateTime.parse(String.valueOf(value),DateTimeFormterGet.getDateTimeFormeter()));
        }else {
            clazz.getDeclaredMethod("set"+firstUpper(fieldName),field.getType()).invoke(obj,value);
        }

    }

    /**
     * 主要是用于生成get和set方法
     * @param str
     * @return
     */
    public static String firstUpper(String str){
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }


}
